package ${package}.customer.service.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import ${package}.customer.constant.MenuStatus;
import ${package}.customer.constant.MenuType;
import ${package}.customer.entity.Menu;
import ${package}.customer.dao.MenuDao;
import ${package}.customer.service.MenuService;
import cn.tannn.jdevelops.exception.built.BusinessException;
import cn.tannn.jdevelops.jpa.service.J2ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

import static ${package}.util.MenuSpecification.*;
/**
 * 菜单
 *
 * @author <a href="https://tannn.cn/">tan</a>
 * @date 2023/12/4 13:25
 */

@Service
public class MenuServiceImpl extends J2ServiceImpl<MenuDao, Menu,Long> implements MenuService {
    public MenuServiceImpl() {
        super(Menu.class);
    }

    @Override
    public void disable(List<String> codes) {
        getJpaBasicsDao().changeStatus(codes, MenuStatus.DISABLE.getStatus());
        // 禁用子级
        disableChild(codes);
    }

    @Override
    public void enabled(List<String> codes) {
        getJpaBasicsDao().changeStatus(codes, MenuStatus.NORMAL.getStatus());
        // 启用父级
        enabledParen(codes);
    }

    @Override
    public List<Menu> getAllExDisabled() {
        return getJpaBasicsDao().findAllByStatusNot(MenuStatus.DISABLE.getStatus());
    }

    @Override
    public List<Tree<String>> getTree(List<Menu> beanList) {
        //配置
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 自定义属性名 都要默认值的
        treeNodeConfig.setWeightKey("sortNumber");
        // 最大递归深度
        treeNodeConfig.setDeep(10);
        //转换器
        return TreeUtil.build(beanList, "0", treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getCode());
                    tree.setParentId(treeNode.getParentCode());
                    tree.setWeight(treeNode.getSort());
                    tree.setName(treeNode.getName());
                    // 扩展属性 ...
                    tree.putExtra("type", treeNode.getType());
                    tree.putExtra("code", treeNode.getCode());
                    tree.putExtra("sourceId", treeNode.getId()+"");
                    tree.putExtra("router", treeNode.getRouter());
                    tree.putExtra("icon", treeNode.getIcon());
                    tree.putExtra("status", treeNode.getStatus());
                    tree.putExtra("component", treeNode.getComponent());
                    tree.putExtra("componentName", treeNode.getComponentName());
                });
    }

    @Override
    public Optional<Menu> verifyParentExist(String parentCode) {
        try {
            if (StringUtils.isNotBlank(parentCode)) {
                if ("0".equals(parentCode)) {
                    return Optional.of(Menu.top());
                }
                Optional<Menu> menu = getJpaBasicsDao().findByCode(parentCode);
                if (menu.isPresent() && menu.get().getStatus() != MenuStatus.DISABLE.getStatus()) {
                    return menu;
                }
            }
            throw new BusinessException("当前父节点不存在，请重新选择");
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            throw new BusinessException("当前父节点不存在，请重新选择");
        }
    }

    @Override
    public void verifyName(String name, String parentCode, String code) {
        List<Menu> entities = getJpaBasicsDao().findAll(eqName(name).and(eqParentCode(parentCode)).and(neCode(code)));
        if (!entities.isEmpty()) {
            throw new BusinessException("同级节点名称重复，请重新填写");
        }
    }

    @Override
    public Optional<Menu> findByCode(String code) {
        return getJpaBasicsDao().findByCode(code);
    }

    @Override
    public List<Menu> findByCode(List<String> codes) {
        return getJpaBasicsDao().findByCodeIn(codes);
    }

    @Override
    public void deleteMenu(List<String> codes) {
        // 删除自己
        getJpaBasicsDao().deleteByCodeIn(codes);
        // 删除子级
        deleteChild(codes);
    }

    @Override
    public List<Menu> getChild(String code, MenuStatus status, MenuType type) {
        return getJpaBasicsDao().findAll(eqStatus(status).and(eqParentCode(code).and(eqType(type))));
    }

    @Override
    public List<Menu> findByMenuStatusAndCodeIn(Integer status, List<String> codes) {
        return getJpaBasicsDao().findByStatusAndCodeIn(status, codes);
    }



    /**
     * 循环禁用子级
     *
     * @param codes codes
     * @date 2022-11-08 16:30:01
     */
    private Boolean disableChild(List<String> codes) {
        List<String> childCode = getJpaBasicsDao().findChild(codes);
        if (childCode != null && !childCode.isEmpty()) {
            // menuStatus 节点状态（0、禁用；1、启用）
            getJpaBasicsDao().changeStatus(codes, 0);
            return disableChild(childCode);
        } else {
            return true;
        }
    }

    /**
     * 循环启用父级
     *
     * @param codes codes
     * @date 2022-11-08 16:35:33
     */
    private Boolean enabledParen(List<String> codes) {
        List<String> paren = getJpaBasicsDao().findParen(codes);
        if (paren != null && !paren.isEmpty()) {
            // menuStatus 节点状态（0、禁用；1、启用）
            getJpaBasicsDao().changeStatus(codes, 1);
            return enabledParen(paren);
        } else {
            return true;
        }
    }


    /**
     * 循环删除子级
     *
     * @param codes codes
     * @return Boolean
     */
    private Boolean deleteChild(List<String> codes) {
        List<String> child = getJpaBasicsDao().findChild(codes);
        // 删除
        if (child != null && !child.isEmpty()) {
            getJpaBasicsDao().deleteByCodeIn(child);
            return deleteChild(child);
        } else {
            return true;
        }
    }
}
